package com.coc.service;

import com.Ostermiller.util.Base64;
import com.coc.bean.CcEloUser;
import com.coc.bean.CcMap;
import com.coc.bean.CcUser;
import com.coc.bean.CocSetting;
import com.coc.bean.res.Dakm;
import com.coc.bean.res.Daks;
import com.coc.bean.res.Elxm;
import com.coc.bean.res.Elxs;
import com.coc.bean.res.Golm;
import com.coc.bean.res.Gols;
import com.coc.bean.war.Camp;
import com.coc.bean.war.Labt;
import com.coc.bean.war.Spel;
import com.coc.bean.war.Tran;
import com.coc.bean.war.Trdk;
import com.coc.dao.Building;
import com.coc.dao.EloUserDAO;
import com.coc.dao.Troops;
import com.coc.util.MemCacheUtil;
import com.coc.util.SignException;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class CocUserService extends BaseService {
	// 魔法研究
	// 改成一次一个,和研究所一样,自动收取魔法
	// type 魔法id
	// t 时间戳
	public void SpellResearch(HttpServletRequest request, JSONObject ht)
			throws Exception {
		String type = getParamValue("q", ht, request);
		long t = Long.parseLong(getParamValue("t", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_spell:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		// 初始化spell(自动收取完工)
		this.initSpell(cm, t, request);
		CcUser cu = cm.getCcuser();
		Spel spel = cm.getSpel();
		Labt labt = cm.getLabt();
		// 没魔法工厂或者升级中
		if (spel == null || spel.getUpgradeEnd() > t) {
			throw new SignException(
					"act_spell:no spellfactory or spellfactory can not work", 2);
		}
		Troops tr = getBuildSettingXML(request).findTrByID(type);

		// 已经完工的魔法1
		int donecount = spel.getCurspell().split(",").length;
		// 魔法还没造完
		if (spel.getResearching().length() > 1) {
			throw new SignException("act_spell:have researching spell ", 2);
		}
		// 魔法工厂等级既是容量,不能超限
		if (spel.getLv() < (donecount + 1)) {
			throw new SignException("act_spell:have researching spell ", 2);
		}
		// spel等级不够造该魔法
		if (tr.getMaker().intValue() > spel.getLv()) {
			throw new SignException("act_spell:spellfactory lv not enough ", 2);
		}
		// 魔法等级默认1级
		int splv = 1;
		// 如果实验室有研究完成过高级魔法,等级置换
		if ((labt != null) && (labt.getDone().indexOf(type) != -1)) {
			splv = Integer.parseInt(labt.getDone().substring(
					labt.getDone().indexOf(type) + type.length() + 1,
					labt.getDone().indexOf(type) + type.length() + 2));
		}
		// 等级;实验室等级;研究费用;升级费用;升级时间
		String str = (String) tr.getLv().get(splv - 1);
		String[] strs = str.split(";");
		String[] cost = strs[2].split(",");
		int gold = 0;
		int elxm = 0;
		int dakm = 0;
		int gem = 0;

		for (int i = 0; i < cost.length; i++) {
			if (cost[i].startsWith("g"))
				gold = Integer.parseInt(cost[i].substring(1));
			else if (cost[i].startsWith("e"))
				elxm = Integer.parseInt(cost[i].substring(1));
			else if (cost[i].startsWith("d"))
				dakm = Integer.parseInt(cost[i].substring(1));
			else if (cost[i].startsWith("m")) {
				gem = Integer.parseInt(cost[i].substring(1));
			}
		}
		if (cu.getGold().intValue() < gold) {
			throw new SignException("act_spell:not enough gold", 2);
		}
		cu.setGold(Integer.valueOf(cu.getGold().intValue() - gold));
		if (cu.getElixir().intValue() < elxm) {
			throw new SignException("act_spell:not enough elixir", 2);
		}
		cu.setElixir(Integer.valueOf(cu.getElixir().intValue() - elxm));
		if (cu.getDark().intValue() < dakm) {
			throw new SignException("act_spell:not enough dark elixir", 2);
		}
		cu.setDark(Integer.valueOf(cu.getDark().intValue() - dakm));
		if (cu.getGem().intValue() < gem) {
			throw new SignException("act_spell:not enough gem", 2);
		}
		cu.setGem(Integer.valueOf(cu.getGem().intValue() - gem));
		spel.setResearching(type);
		spel.setResearchbeg(t);
		cm.setCcuser(cu);
		cm.setSpel(spel);
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	public void CancelSpellResearch(HttpServletRequest request, JSONObject ht)
			throws Exception {
		String type = getParamValue("type", ht, request);
		long t = Long.parseLong(getParamValue("t", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_cancelspell:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		CcUser cu = cm.getCcuser();
		Spel spel = cm.getSpel();
		Labt labt = cm.getLabt();
		// 没魔法工厂或者升级中
		if (spel == null || spel.getUpgradeEnd() > t) {
			throw new SignException(
					"act_cancelspell:no spellfactory or spellfactory can not work",
					2);
		}
		Troops tr = getBuildSettingXML(request).findTrByID(type);

		// 没魔法
		if (spel.getResearching().length() < 1) {
			throw new SignException("act_cancelspell:no spell to cancel", 2);
		}
		type = spel.getResearching();
		int splv = 1;
		if ((labt != null) && (labt.getDone().indexOf(type) != -1)) {
			splv = Integer.parseInt(labt.getDone().substring(
					labt.getDone().indexOf(type) + type.length() + 1,
					labt.getDone().indexOf(type) + type.length() + 2));
		}
		String str = (String) tr.getLv().get(splv - 1);
		String[] strs = str.split(";");
		String[] cost = strs[2].split(",");
		int regold = 0;
		int reelxm = 0;
		int redakm = 0;
		int regem = 0;
		for (int i = 0; i < cost.length; i++) {
			if (cost[i].startsWith("g")) {
				regold = regold + Integer.parseInt(cost[i].substring(1)) / 2;
			} else if (cost[i].startsWith("e")) {
				reelxm = reelxm + Integer.parseInt(cost[i].substring(1)) / 2;
			} else if (cost[i].startsWith("d")) {
				redakm = redakm + Integer.parseInt(cost[i].substring(1)) / 2;
			} else if (cost[i].startsWith("m")) {
				regem = regem + Integer.parseInt(cost[i].substring(1)) / 2;
			}
		}

		cu.setGold(Integer.valueOf(cu.getGold().intValue() + regold));
		cu.setElixir(Integer.valueOf(cu.getElixir().intValue() + reelxm));
		cu.setDark(Integer.valueOf(cu.getDark().intValue() + redakm));
		cu.setGem(Integer.valueOf(cu.getGem().intValue() + regem));
		spel.setResearching("");
		cm.setCcuser(cu);
		cm.setSpel(spel);
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	// 实验室研究
	// 研究结果不自动取,需要手动
	// t - 服务器时间
	// type - 兵种id
	public void LabResearch(HttpServletRequest request, JSONObject ht)
			throws Exception {
		String type = getParamValue("type", ht, request);
		long t = Long.parseLong(getParamValue("t", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_labresearch:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);

		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		CcUser cu = cm.getCcuser();
		Labt lab = cm.getLabt();
		// 实验室在升级,不能研究
		if ((lab == null) || (lab.getUpgradeEnd() > t)) {
			throw new SignException(
					"act_labresearch:no lab or lab can not work", 2);
		}
		// 已经有研究队列,不能研究
		// 摈弃不自动取,需要手动,不用检测是否研究完成
		if (lab.getResearching().length() > 1) {
			throw new SignException("act_labresearch:lab researching", 2);
		}

		Troops tr = getBuildSettingXML(request).findTrByID(type);
		int pos = cm.getLabt().getDone().indexOf(type);
		// 所有兵种魔法等级初始都为1,所以目标等级为2,
		int tragetlv = 2;
		// 如果该魔法,兵种已经不是1级,那么+1
		if (pos != -1) {
			tragetlv = Integer.parseInt(cm.getLabt().getDone().substring(
					pos + type.length() + 1, pos + type.length() + 2)) + 1;
		}
		// 等级;实验室等级;研究费用;升级费用;升级时间
		String[] str = ((String) tr.getLv().get(tragetlv - 1)).split(";");
		int lablv = Integer.parseInt(str[1]);
		// 实验室等级不够
		if (cm.getLabt().getLv() < lablv) {
			throw new SignException("act_labresearch:no enough lab lv", 2);
		}
		// 扣钱
		String[] cost = str[3].split(",");
		int gold = 0;
		int elxm = 0;
		int dakm = 0;
		int gem = 0;
		for (int i = 0; i < cost.length; i++) {
			if (cost[i].startsWith("g"))
				gold = Integer.parseInt(cost[i].substring(1));
			else if (cost[i].startsWith("e"))
				elxm = Integer.parseInt(cost[i].substring(1));
			else if (cost[i].startsWith("d"))
				dakm = Integer.parseInt(cost[i].substring(1));
			else if (cost[i].startsWith("m")) {
				gem = Integer.parseInt(cost[i].substring(1));
			}
		}
		if (cu.getGold().intValue() < gold) {
			throw new SignException("act_labresearch:no enough gold", 2);
		}
		cu.setGold(Integer.valueOf(cu.getGold().intValue() - gold));
		if (cu.getElixir().intValue() < elxm) {
			throw new SignException("act_labresearch:no enough elixir", 2);
		}
		cu.setElixir(Integer.valueOf(cu.getElixir().intValue() - elxm));
		if (cu.getDark().intValue() < dakm) {
			throw new SignException("act_labresearch:no enough dark elixir", 2);
		}
		cu.setDark(Integer.valueOf(cu.getDark().intValue() - dakm));
		if (cu.getGem().intValue() < gem) {
			throw new SignException("act_labresearch:no enough gem", 2);
		}
		cu.setGem(Integer.valueOf(cu.getGem().intValue() - gem));
		cm.setCcuser(cu);
		lab.setResearching(type);
		lab.setResearchbeg(t);
		lab.setResearchend((t + Integer.parseInt(str[4]) * 1000L));
		cm.setLabt(lab);
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	// 取消兵种,升级研究
	// t - 服务器时间
	// type - 兵种id/魔法id
	// 原则上不可能存在已经研究好的要取消的情况
	public void LabCancel(HttpServletRequest request, JSONObject ht)
			throws Exception {

		long t = Long.parseLong(getParamValue("t", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		long now = System.currentTimeMillis();
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_cancellabresearch:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		Labt lab = cm.getLabt();
		// 先指定退钱扣一半
		int returnrate = 2;

		// 没实验室或者建筑物正在升级
		if ((lab == null) || (lab.getUpgradeEnd() > now)) {
			throw new SignException(
					"act_cancellabresearch:no lab or lab can not work", 2);
		}
		// 没有研究队列,不能取消
		if (lab.getResearching().length() < 1) {
			throw new SignException("act_cancellabresearch:no researching", 2);
		}
		String type = lab.getResearching();
		Troops tr = getBuildSettingXML(request).findTrByID(type);
		int pos = lab.getDone().indexOf(type);
		int tragetlv = 2;
		if (pos != -1) {
			tragetlv = Integer.parseInt(lab.getDone().substring(
					pos + type.length() + 1, pos + type.length() + 2));
		}
		// 退钱,退一半
		String[] str = ((String) tr.getLv().get(tragetlv - 1)).split(";");
		String[] cost = str[3].split(",");
		int gold = 0;
		int elxm = 0;
		int dakm = 0;
		int gem = 0;
		for (int i = 0; i < cost.length; i++) {
			if (cost[i].startsWith("g")) {
				gold = Integer.parseInt(cost[i].substring(1)) / returnrate;
				cm.getCcuser().setGold(
						Integer.valueOf(cm.getCcuser().getGold().intValue()
								+ gold));
			} else if (cost[i].startsWith("e")) {
				elxm = Integer.parseInt(cost[i].substring(1)) / returnrate;
				cm.getCcuser().setElixir(
						Integer.valueOf(cm.getCcuser().getElixir().intValue()
								+ elxm));
			} else if (cost[i].startsWith("d")) {
				dakm = Integer.parseInt(cost[i].substring(1)) / returnrate;
				cm.getCcuser().setDark(
						Integer.valueOf(cm.getCcuser().getDark().intValue()
								+ dakm));
			} else if (cost[i].startsWith("m")) {
				gem = Integer.parseInt(cost[i].substring(1)) / returnrate;
				cm.getCcuser().setGem(
						Integer.valueOf(cm.getCcuser().getGem().intValue()
								+ gem));
			}
		}
		lab.setResearching("");
		lab.setResearchend(0);
		lab.setResearchbeg(0);
		cm.setLabt(lab);
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	// 实验室升级成功后获取升级结果
	public void LabGet(HttpServletRequest request, JSONObject ht)
			throws Exception {

		long t = Long.parseLong(getParamValue("t", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_getlab:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		Labt lab = cm.getLabt();
		// 没实验室或者实验室正在升级建筑
		if ((lab == null) || (lab.getUpgradeEnd() > t)) {
			throw new SignException("act_getlab:no lab or lab can not work", 2);
		}
		// 如果有东西在研究
		if (lab.getResearching().length() > 1) {
			String type = lab.getResearching();
			// 在t时间点没研究完
			if (lab.getResearchend() > t) {
				throw new SignException("act_getlab:researching,can not get", 2);
			}
			lab.setResearching("");
			int pos = lab.getDone().indexOf(type);
			if (pos == -1) {
				if (lab.getDone().length() == 0)
					lab.setDone(type + "|2");
				else
					lab.setDone(lab.getDone() + "," + type + "|2");
			} else {
				int curlv = Integer.parseInt(lab.getDone().substring(
						pos + type.length() + 1, pos + type.length() + 2));
				lab.setDone(lab.getDone().replace(type + "|" + curlv,
						type + "|" + (curlv + 1)));
			}
		} else {
			throw new SignException("act_getlab:no research to get", 2);
		}
		cm.setLabt(lab);
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	// 收取矿,紫水,黑水
	// t - 服务器时间
	// type - 建筑物类型(ELXM / GOLM / DAKM)
	// id - 在本建筑物类型内的序号(序号从 0 开始)
	// 加速生产时候会主动收取一次,不会存在生产时间跨越(普通+加速+普通)3个区间,最多俩个区间(加速,普通)
	public void Collect(HttpServletRequest request, JSONObject ht)
			throws Exception {

		String type = getParamValue("type", ht, request);
		long t = Long.parseLong(getParamValue("t", ht, request));
		int index = Integer.parseInt(getParamValue("id", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_collect:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}

		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		CcUser cu = cm.getCcuser();
		// 金矿
		if (type.equals("GOLM")) {
			Golm tmp = (Golm) cm.getGolms().get(index);
			// 在升级
			if (tmp.getUpgradeEnd() > t) {
				throw new SignException(
						"act_collect:no GOLM or GOLM can not work", 2);
			}
			// 取生产额
			int value = getProductValue(request, t, type, tmp);
			int max = getMaxGold(cm, t, request);
			int curgold = cu.getGold().intValue();
			// 超出金库上限就剩余部分到left中
			if (value + curgold > max) {
				cu.setGold(Integer.valueOf(max));
				value = max + value - curgold;
			} else {
				cu.setGold(Integer.valueOf(curgold + value));
				value = 0;
			}
			tmp.setLeft(0);
			// 超出部分反推时间回去存入lefttime,left=0
			if (value > 0) {
				int lefttime = this.getLeftTime(request, t, type, tmp, value);
				tmp.setLefttime(t - lefttime * 1000L);
			} else {
				tmp.setLefttime(t);
			}
			cm.getGolms().set(index, tmp);
		} else if (type.equals("ELXM")) {
			Elxm tmp = (Elxm) cm.getElxms().get(index);
			if (tmp.getUpgradeEnd() > t) {
				throw new SignException(
						"act_collect:no ELXM or ELXM can not work", 2);
			}
			int value = getProductValue(request, t, type, tmp);
			int max = getMaxElxs(cm, t, request);
			int curgold = cu.getElixir().intValue();
			if (value + curgold > max) {
				cu.setElixir(Integer.valueOf(max));
				value = max + value - curgold;
			} else {
				cu.setElixir(Integer.valueOf(curgold + value));
				value = 0;
			}

			tmp.setLeft(0);
			// 超出部分反推时间回去存入lefttime,left=0
			if (value > 0) {
				int lefttime = this.getLeftTime(request, t, type, tmp, value);
				tmp.setLefttime(t - lefttime * 1000L);
			} else {
				tmp.setLefttime(t);
			}
			cm.getElxms().set(index, tmp);
		} else if (type.equals("DAKM")) {
			Dakm tmp = (Dakm) cm.getDakms().get(index);
			if (tmp.getUpgradeEnd() > t) {
				throw new SignException(
						"act_collect:no DAKM or DAKM can not work", 2);
			}
			int value = getProductValue(request, t, type, tmp);
			int max = getMaxDaks(cm, t, request);
			int curgold = cu.getDark().intValue();
			if (value + curgold > max) {
				cu.setDark(Integer.valueOf(max));
				value = max + value - curgold;
			} else {
				cu.setDark(Integer.valueOf(curgold + value));
				value = 0;
			}
			tmp.setLeft(0);
			// 超出部分反推时间回去存入lefttime,left=0
			if (value > 0) {
				int lefttime = this.getLeftTime(request, t, type, tmp, value);
				tmp.setLefttime(t - lefttime * 1000L);
			} else {
				tmp.setLefttime(t);
			}
			cm.getDakms().set(index, tmp);
		}
		cm.setCcuser(cu);
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	// 造兵
	// type - BARK/BKDK (普通/黑水训练营)
	// id - 训练营的序号
	// t - 服务器时间
	// acts - 兵种id|数量, ......
	// 同一个兵营里，造兵队列最多只能排4个兵种 new
	// 不考虑减少
	public void Tran(HttpServletRequest request, JSONObject ht)
			throws Exception {

		String type = getParamValue("type", ht, request);
		String acts = getParamValue("q", ht, request);
		long t = Long.parseLong(getParamValue("t", ht, request));
		int index = Integer.parseInt(getParamValue("id", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_train:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		CcUser cu = cm.getCcuser();
		Hashtable<String, String> allUnit = new Hashtable<String, String>();
		// 新增队列
		List<String> addUnitList = new ArrayList<String>();
		// 把本次兵种增减数量打散
		String[] units = acts.split(",");
		for (int i = 0; i < units.length; i++) {
			String tmp_type = units[i].substring(0, units[i].indexOf("|"));
			int count = Integer.parseInt(units[i].substring(units[i]
					.indexOf("|") + 1));
			for (int j = 0; j < count; j++)
				addUnitList.add(tmp_type);
		}
		// 初始化训练营,把当前时间点已经造好的兵更新
		initAllTrain(cm, t, request);
		Labt labt = cm.getLabt();
		int empty = getCampEmpty(cm, t, request);
		// 新增的大于空位
		if (addUnitList.size() > empty) {
			throw new SignException("act_train:not enough space", 2);
		}
		if (type.equals("BARK")) {
			Tran tran = (Tran) cm.getBarks().get(index);
			String res = tran.getProcess();
			// 队列为空,新增完开始时间为t
			// 否则为initAllTrain中设定时间
			if (res.length() < 1) {
				tran.setProcessbeg(t);
			}
			// 开始加
			for (int i = 0; i < addUnitList.size(); i++) {
				Troops tr = getBuildSettingXML(request).findTrByID(
						(String) addUnitList.get(i));
				if (tr.getMaker().intValue() > tran.getLv()) {
					throw new SignException("act_train:not enough lv", 2);
				}
				int splv = 1;
				if ((labt != null) && (labt.getDone().indexOf(type) != -1)) {
					splv = Integer.parseInt(labt.getDone().substring(
							labt.getDone().indexOf(type) + type.length() + 1,
							labt.getDone().indexOf(type) + type.length() + 2));
				}
				String str = (String) tr.getLv().get(splv - 1);
				String[] strs = str.split(";");
				String[] cost = strs[2].split(",");
				// 消耗资源
				int gold = 0;
				int elxm = 0;
				int dakm = 0;
				int gem = 0;
				for (int j = 0; j < cost.length; j++) {
					if (cost[j].startsWith("g"))
						gold = Integer.parseInt(cost[j].substring(1));
					else if (cost[j].startsWith("e"))
						elxm = Integer.parseInt(cost[j].substring(1));
					else if (cost[j].startsWith("d"))
						dakm = Integer.parseInt(cost[j].substring(1));
					else if (cost[j].startsWith("m")) {
						gem = Integer.parseInt(cost[j].substring(1));
					}
				}
				if (cu.getGold().intValue() < gold) {
					throw new SignException("act_train:not enough gold", 2);
				}
				cu.setGold(Integer.valueOf(cu.getGold().intValue() - gold));
				if (cu.getElixir().intValue() < elxm) {
					throw new SignException("act_train:not enough elixir", 2);
				}
				cu.setElixir(Integer.valueOf(cu.getElixir().intValue() - elxm));
				if (cu.getDark().intValue() < dakm) {
					throw new SignException("act_train:not enough dark elixir",
							2);
				}
				cu.setDark(Integer.valueOf(cu.getDark().intValue() - dakm));
				if (cu.getGem().intValue() < gem) {
					throw new SignException("act_train:not enough gem", 2);
				}
				cu.setGem(Integer.valueOf(cu.getGem().intValue() - gem));
				int pos = res.indexOf((String) addUnitList.get(i));
				// 现在队列没有该兵种,新增队列
				if (pos == -1) {
					if (res.equals("")) {
						if (allUnit.containsKey(addUnitList.get(i))) {
							allUnit.put(addUnitList.get(i), addUnitList.get(i));
						}
						res = addUnitList.get(i) + "|1";
					} else
						res = res + "," + (String) addUnitList.get(i) + "|1";
				} else {// 有则数量加1
					int curcount = Integer.parseInt(res.substring(pos
							+ ((String) addUnitList.get(i)).length() + 1, pos
							+ ((String) addUnitList.get(i)).length() + 2));
					res = res.replace((String) addUnitList.get(i) + "|"
							+ curcount, (String) addUnitList.get(i) + "|"
							+ (curcount + 1));
				}
			}
			tran.setProcess(res);
			cm.getBarks().set(index, tran);
		} else {
			Trdk tran = (Trdk) cm.getBkdks().get(index);
			String res = tran.getProcess();
			// 队列为空,新增完开始时间为t
			// 否则为initAllTrain中设定时间
			if (res.length() < 1) {
				tran.setProcessbeg(t);
			}
			for (int i = 0; i < addUnitList.size(); i++) {
				Troops tr = getBuildSettingXML(request).findTrByID(
						(String) addUnitList.get(i));

				if (tr.getMaker().intValue() > tran.getLv()) {
					throw new SignException("act_train:not enough lv", 2);
				}

				int splv = 1;
				if ((labt != null) && (labt.getDone().indexOf(type) != -1)) {
					splv = Integer.parseInt(labt.getDone().substring(
							labt.getDone().indexOf(type) + type.length() + 1,
							labt.getDone().indexOf(type) + type.length() + 2));
				}
				String str = (String) tr.getLv().get(splv - 1);

				String[] strs = str.split(";");
				String[] cost = strs[2].split(",");
				int gold = 0;
				int elxm = 0;
				int dakm = 0;
				int gem = 0;

				for (int j = 0; j < cost.length; j++) {
					if (cost[j].startsWith("g"))
						gold = Integer.parseInt(cost[j].substring(1));
					else if (cost[j].startsWith("e"))
						elxm = Integer.parseInt(cost[j].substring(1));
					else if (cost[j].startsWith("d"))
						dakm = Integer.parseInt(cost[j].substring(1));
					else if (cost[j].startsWith("m")) {
						gem = Integer.parseInt(cost[j].substring(1));
					}
				}
				if (cu.getGold().intValue() < gold) {
					throw new SignException("act_train:not enough gold", 2);
				}
				cu.setGold(Integer.valueOf(cu.getGold().intValue() - gold));
				if (cu.getElixir().intValue() < elxm) {
					throw new SignException("act_train:not enough elixir", 2);
				}
				cu.setElixir(Integer.valueOf(cu.getElixir().intValue() - elxm));
				if (cu.getDark().intValue() < dakm) {
					throw new SignException("act_train:not enough dark elixir",
							2);
				}
				cu.setDark(Integer.valueOf(cu.getDark().intValue() - dakm));
				if (cu.getGem().intValue() < gem) {
					throw new SignException("act_train:not enough gem", 2);
				}
				cu.setGem(Integer.valueOf(cu.getGem().intValue() - gem));
				int pos = res.indexOf((String) addUnitList.get(i));

				if (pos == -1) {
					if (res.equals("")) {
						res = (String) addUnitList.get(i) + "|1";
					} else
						res = res + "," + (String) addUnitList.get(i) + "|1";
				} else {
					int curcount = Integer.parseInt(res.substring(pos
							+ ((String) addUnitList.get(i)).length() + 1, pos
							+ ((String) addUnitList.get(i)).length() + 2));

					res = res.replace((String) addUnitList.get(i) + "|"
							+ curcount, (String) addUnitList.get(i) + "|"
							+ (curcount + 1));
				}
			}

			tran.setProcess(res);
			cm.getBkdks().set(index, tran);
		}
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	// 取消造兵
	// type - BARK/BKDK (普通/黑水训练营)
	// id - 训练营的序号
	// t - 服务器时间
	// acts - 兵种id|数量, ......
	// -当前队列第一个兵被取消时候加验算,队列第一个兵变成下一个坑位,
	// 意味着begtime=t(因为之前begtime是相对于取消那个兵的,兵被取消了,已用时间归0)
	public void CancelTran(HttpServletRequest request, JSONObject ht)
			throws Exception {

		boolean isNewTime = false;
		String type = getParamValue("type", ht, request);
		String acts = getParamValue("q", ht, request);
		long t = Long.parseLong(getParamValue("t", ht, request));
		int index = Integer.parseInt(getParamValue("id", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_canceltrain:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		CcUser cu = cm.getCcuser();
		// 减少队列
		List<String> removeUnitList = new ArrayList<String>();
		// 把本次兵减少数量打散
		String[] units = acts.split(",");
		for (int i = 0; i < units.length; i++) {
			String tmp_type = units[i].substring(0, units[i].indexOf("|"));
			int count = Integer.parseInt(units[i].substring(units[i]
					.indexOf("|") + 1));
			if (count < 0)
				count *= -1;
			for (int j = 0; j < count; j++) {
				removeUnitList.add(tmp_type);
			}

		}
		// 初始化训练营,把当前时间点已经造好的兵更新
		initAllTrain(cm, t, request);
		// 根据兵种等级计算退款
		Labt labt = cm.getLabt();
		if (type.equals("BARK")) {
			Tran tran = (Tran) cm.getBarks().get(index);
			String res = tran.getProcess();
			// 队列为空,没有兵种可以取消
			if (res.length() < 1) {
				throw new SignException("act_canceltrain:no unit to cancel", 2);
			}
			// 首个兵种
			String first = res.substring(0, 3);
			int regold = 0;
			int reelxm = 0;
			int redakm = 0;
			int regem = 0;
			// 先移除
			for (int i = 0; i < removeUnitList.size(); i++) {
				String reSpell = removeUnitList.get(i);
				int pos = res.indexOf(reSpell);
				// 队列没有可以移除的兵种
				if (pos == -1) {
					throw new SignException(
							"act_canceltrain:no unit to cancel", 2);
				}
				// 当前数量
				int curcount = Integer.parseInt(res.substring(pos
						+ reSpell.length() + 1, pos + reSpell.length() + 2));
				// 只剩一个,移除整个坑位,否则数量-1
				if (curcount == 1) {
					// 首坑被移除,要重置begtime
					if (reSpell.indexOf(first) != -1) {
						isNewTime = true;
					}
					res = res.replace(reSpell + "|" + curcount, "");
				} else {
					res = res.replace(reSpell + "|" + curcount, reSpell + "|"
							+ (curcount - 1));
				}
				if (res.startsWith(",")) {
					res = res.substring(1);
				}
				Troops tr = getBuildSettingXML(request).findTrByID(reSpell);
				int splv = 1;
				if ((labt != null) && (labt.getDone().indexOf(reSpell) != -1)) {
					splv = Integer.parseInt(labt.getDone().substring(
							labt.getDone().indexOf(reSpell) + reSpell.length()
									+ 1,
							labt.getDone().indexOf(reSpell) + reSpell.length()
									+ 2));
				}
				String str = (String) tr.getLv().get(splv - 1);

				String[] strs = str.split(";");
				String[] cost = strs[2].split(",");
				// 还钱
				for (int j = 0; j < cost.length; j++) {
					if (cost[j].startsWith("g")) {
						regold = regold
								+ Integer.parseInt(cost[j].substring(1));
					} else if (cost[j].startsWith("e")) {
						reelxm = reelxm
								+ Integer.parseInt(cost[j].substring(1));
					} else if (cost[j].startsWith("d")) {
						redakm = redakm
								+ Integer.parseInt(cost[j].substring(1));
					} else if (cost[j].startsWith("m")) {
						regem = regem + Integer.parseInt(cost[j].substring(1));
					}
				}
			}
			cu.setGold(Integer.valueOf(cu.getGold().intValue() + regold));
			cu.setElixir(Integer.valueOf(cu.getElixir().intValue() + reelxm));
			cu.setDark(Integer.valueOf(cu.getDark().intValue() + redakm));
			cu.setGem(Integer.valueOf(cu.getGem().intValue() + regem));
			checkRes(res);
			// 如果第一坑位兵种被全部移除,,开始时间设置成0
			if (isNewTime) {
				tran.setProcessbeg(t);
			}
			// 如果移除兵种后队列为空,开始时间设置成0
			if (res.length() < 1) {
				tran.setProcessbeg(0);
			}
			tran.setProcess(res);
			cm.getBarks().set(index, tran);
		} else {
			Trdk tran = (Trdk) cm.getBkdks().get(index);
			String res = tran.getProcess();
			// 队列为空,没有兵种可以取消
			if (res.length() < 1) {
				throw new SignException("act_canceltrain:no unit to cancel", 2);
			}
			// 首个兵种
			String first = res.substring(0, 3);
			int regold = 0;
			int reelxm = 0;
			int redakm = 0;
			int regem = 0;
			// 先移除
			for (int i = 0; i < removeUnitList.size(); i++) {
				String reSpell = removeUnitList.get(i);
				int pos = res.indexOf(reSpell);
				// 队列没有可以移除的兵种
				if (pos == -1) {
					throw new SignException(
							"act_canceltrain:no unit to cancel", 2);
				}
				// 当前数量
				int curcount = Integer.parseInt(res.substring(pos
						+ reSpell.length() + 1, pos + reSpell.length() + 2));
				// 只剩一个,移除整个坑位,否则数量-1
				if (curcount == 1) {
					// 首坑被移除,要重置begtime
					if (reSpell.indexOf(first) != -1) {
						isNewTime = true;
					}
					res = res.replace(reSpell + "|" + curcount, "");
				} else {
					res = res.replace(reSpell + "|" + curcount, reSpell + "|"
							+ (curcount - 1));
				}
				if (res.startsWith(",")) {
					res = res.substring(1);
				}
				Troops tr = getBuildSettingXML(request).findTrByID(reSpell);
				int splv = 1;
				if ((labt != null) && (labt.getDone().indexOf(reSpell) != -1)) {
					splv = Integer.parseInt(labt.getDone().substring(
							labt.getDone().indexOf(reSpell) + reSpell.length()
									+ 1,
							labt.getDone().indexOf(reSpell) + reSpell.length()
									+ 2));
				}
				String str = (String) tr.getLv().get(splv - 1);

				String[] strs = str.split(";");
				String[] cost = strs[2].split(",");
				// 还钱
				for (int j = 0; j < cost.length; j++) {
					if (cost[j].startsWith("g")) {
						regold = regold
								+ Integer.parseInt(cost[j].substring(1));
					} else if (cost[j].startsWith("e")) {
						reelxm = reelxm
								+ Integer.parseInt(cost[j].substring(1));
					} else if (cost[j].startsWith("d")) {
						redakm = redakm
								+ Integer.parseInt(cost[j].substring(1));
					} else if (cost[j].startsWith("m")) {
						regem = regem + Integer.parseInt(cost[j].substring(1));
					}
				}
			}
			cu.setGold(Integer.valueOf(cu.getGold().intValue() + regold));
			cu.setElixir(Integer.valueOf(cu.getElixir().intValue() + reelxm));
			cu.setDark(Integer.valueOf(cu.getDark().intValue() + redakm));
			cu.setGem(Integer.valueOf(cu.getGem().intValue() + regem));
			checkRes(res);
			// 如果第一坑位兵种被全部移除,,开始时间设置成0
			if (isNewTime) {
				tran.setProcessbeg(t);
			}
			// 如果移除兵种后队列为空,开始时间设置成0
			if (res.length() < 1) {
				tran.setProcessbeg(0);
			}

			tran.setProcess(res);
			cm.getBkdks().set(index, tran);
		}
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	// 造兵秒杀
	// t - 服务器时间
	// type - BARK/BKDK (普通/黑水训练营/法术工厂)
	// id - 训练营的序号
	// 时间对应宝石价格先随意指定
	public void TranBoost(HttpServletRequest request, JSONObject ht)
			throws Exception {
		String type = getParamValue("type", ht, request);
		int index = Integer.parseInt(getParamValue("id", ht, request));
		long t = Long.parseLong(getParamValue("t", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// 1分钟1宝石,后期改成xml配置
		// int cost = this.getBuildSettingXML(request).SecondPerGem;
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_tranboost:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		CcUser cu = cm.getCcuser();
		// 初始化训练营,把当前时间点已经造好的兵更新
		if (type.equals("BARK")) {
			Tran tran = (Tran) cm.getBarks().get(index);
			// 开始时间,用于算出结束时间,结束时间-t既是秒杀时间
			long begtime = tran.getProcessbeg();
			// 当前建造队列
			String[] units = tran.getProcess().split(",");
			// 逐兵种循环是否完工
			for (int j = 0; j < units.length; j++) {
				// 兵种类型
				String tmp_type = units[j].substring(0, units[j].indexOf("|"));
				// 数量
				int count = Integer.parseInt(units[j].substring(units[j]
						.indexOf("|") + 1));
				Troops trs = getBuildSettingXML(request).findTrByID(tmp_type);
				// 单兵种循环
				for (int z = 0; z < count; z++) {
					begtime = begtime + trs.getTime() * 1000L;
				}

			}
			int needgem = this.getNeedGemFromMS(request, (begtime - t));
			if (cu.getGem().intValue() < needgem) {
				throw new SignException("act_labresearch:no enough gem", 2);
			}
			cu.setGem(cu.getGem() - needgem);
			tran.setProcessbeg(0);
			cm.getBarks().set(index, tran);
			cm.setCcuser(cu);
			initAllTrain(cm, t, request);
		} else if (type.equals("BKDK")) {
			Trdk tran = (Trdk) cm.getBkdks().get(index);
			// 开始时间,用于算出结束时间,结束时间-t既是秒杀时间
			long begtime = tran.getProcessbeg();
			// 当前建造队列
			String[] units = tran.getProcess().split(",");
			// 逐兵种循环是否完工
			for (int j = 0; j < units.length; j++) {
				// 兵种类型
				String tmp_type = units[j].substring(0, units[j].indexOf("|"));
				// 数量
				int count = Integer.parseInt(units[j].substring(units[j]
						.indexOf("|") + 1));
				Troops trs = getBuildSettingXML(request).findTrByID(tmp_type);
				// 单兵种循环
				for (int z = 0; z < count; z++) {
					begtime = begtime + trs.getTime() * 1000L;
				}

			}
			int needgem = this.getNeedGemFromMS(request, (begtime - t));
			if (cu.getGem().intValue() < needgem) {
				throw new SignException("act_labresearch:no enough gem", 2);
			}
			cu.setGem(cu.getGem() - needgem);
			tran.setProcessbeg(0);
			cm.getBkdks().set(index, tran);
			cm.setCcuser(cu);
		}
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);

	}

	// 魔法秒杀
	public void SpellBoost(HttpServletRequest request, JSONObject ht)
			throws Exception {
		long t = Long.parseLong(getParamValue("t", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_spellboost:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		this.initSpell(cm, t, request);
		CcUser cu = cm.getCcuser();
		Spel spel = cm.getSpel();
		if (spel.getResearching().length() > 1) {
			String type = spel.getResearching();
			Troops tr = getBuildSettingXML(request).findTrByID(type);
			// 时间完工时间
			long donetime = spel.getResearchbeg() + tr.getTime();
			int needgem = this.getNeedGemFromMS(request, (donetime - t));
			if (cu.getGem().intValue() < needgem) {
				throw new SignException("act_spellboost:not enough gem", 2);
			}
			cu.setGem(cu.getGem() - needgem);
			spel.setResearchbeg(0);
		} else {
			// 没魔法在研究,无需秒杀
			throw new SignException("act_spellboost:not researching", 2);
		}
		cm.setSpel(spel);
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	// 实验室秒杀
	public void LabBoost(HttpServletRequest request, JSONObject ht)
			throws Exception {
		long t = Long.parseLong(getParamValue("t", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_labboost:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		CcUser cu = cm.getCcuser();
		Labt labt = cm.getLabt();
		if (labt.getResearching().length() > 1) {
			int needgem = this.getNeedGemFromMS(request, (labt.getResearchend() - t));
			if (cu.getGem().intValue() < needgem) {
				throw new SignException("act_labboost:no enough gem", 2);
			}
			cu.setGem(cu.getGem() - needgem);
			String type = labt.getResearching();
			labt.setResearching("");
			labt.setResearchend(0);
			labt.setResearchbeg(0);
			//秒杀后加done里面相应等级
			int pos = labt.getDone().indexOf(type);
			if (pos == -1) {
				if (labt.getDone().length() == 0)
					labt.setDone(type + "|2");
				else
					labt.setDone(labt.getDone() + "," + type + "|2");
			} else {
				int curlv = Integer.parseInt(labt.getDone().substring(
						pos + type.length() + 1, pos + type.length() + 2));
				labt.setDone(labt.getDone().replace(type + "|" + curlv,
						type + "|" + (curlv + 1)));
			}
		} else {
			// 没魔法在研究,无需秒杀
			throw new SignException("act_labboost:no Researching", 2);
		}
		cm.setLabt(labt);
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);

	}

	// 矿脉双倍生产
	// left永远为0,lefttime改为值为0时的时间(不一定都等于t)
	// 暂时不开放加速造兵
	public void MineBoost(HttpServletRequest request, JSONObject ht)
			throws Exception {
		String type = getParamValue("type", ht, request);
		long t = Long.parseLong(getParamValue("t", ht, request));
		int index = Integer.parseInt(getParamValue("id", ht, request));
		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcEloUser ceu = getEloUserDAO(request).findByID(id);
		// t比动作时间大,说明已经运行过了,本次可能因为网络问题导致上次动作包没收到回执
		// 客户端把2次动作间隔之间的动作包一起打包,重新发包,直接跳过就好
		// 比now大,作弊
		if (t > System.currentTimeMillis()) {
			throw new SignException("act_mineboost:t>now", 2);
		}
		if (t < ceu.getLastaction()) {
			return;
		}
		ceu.setLastaction(t);
		getEloUserDAO(request).saveOrUpdate(ceu);
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		CcUser cu = cm.getCcuser();
		if (type.equals("GOLM")) {
			Golm tmp = (Golm) cm.getGolms().get(index);
			if (tmp.getUpgradeEnd() > t) {
				throw new SignException(
						"act_mineboost:no mine or mine can not work", 2);
			}
			Building bu = getBuildSettingXML(request).findBuByID(type);
			// 类型;需求等级(HT/User);花费;建造时间;矿脉容量/dect总数;生产速率;建造经验;加速费用;
			String[] strs = ((String) bu.getLv().get(tmp.getLv() - 1))
					.split(";");
			// String costtype = strs[7].substring(0, 1);
			// 先直接用宝石,不判断货币类型
			int costneed = Integer.parseInt(strs[7].substring(1));
			if (cu.getGem().intValue() < costneed) {
				throw new SignException("act_boost:not enough gem", 2);
			}
			// 已经加速中不能重复加速
			if (tmp.getBoosttime2() >= t) {
				throw new SignException("act_boost:last boost is not end", 2);
			}
			cu.setGem(Integer.valueOf(cu.getGem().intValue() - costneed));
			// 加速时候先收取一次
			int value = getProductValue(request, t, type, tmp);
			// 玩家金库容量
			int max = getMaxGold(cm, t, request);
			// 当前金币数
			int curgold = cu.getGold().intValue();
			// 实际生产数量上限为CAP,剩余数量在这基础上减少
			if (value + curgold > max) {
				cu.setGold(Integer.valueOf(max));
				value = max + value - curgold;
			} else {
				cu.setGold(Integer.valueOf(curgold + value));
				value = 0;
			}
			// 超出部分反推时间回去存入lefttime,left=0
			if (value > 0) {
				int lefttime = this.getLeftTime(request, t, type, tmp, value);
				tmp.setLefttime(t - lefttime * 1000L);
			} else {
				tmp.setLefttime(t);
			}

			// 开始加速时间
			tmp.setBoosttime(t);
			tmp.setBoosttime2(t + bu.getSpeedboos() * 1000L);
			tmp.setLeft(0);

			cm.getGolms().set(index, tmp);
		} else if (type.equals("ELXM")) {
			Elxm tmp = (Elxm) cm.getElxms().get(index);
			if (tmp.getUpgradeEnd() > t) {
				throw new SignException(
						"act_boost:no ELXM or ELXM can not work", 2);
			}
			Building bu = getBuildSettingXML(request).findBuByID(type);
			String[] strs = ((String) bu.getLv().get(tmp.getLv() - 1))
					.split(";");
			// String costtype = strs[7].substring(0, 1);
			int costneed = Integer.parseInt(strs[7].substring(1));
			if (cu.getGem().intValue() < costneed) {
				throw new SignException("act_boost:not enough gem", 2);
			}
			// 已经加速中不能重复加速
			if (tmp.getBoosttime2() >= t) {
				throw new SignException("act_boost:last boost is not end", 2);
			}
			cu.setGem(Integer.valueOf(cu.getGem().intValue() - costneed));
			// 加速时候先收取一次
			int value = getProductValue(request, t, type, tmp);
			int max = getMaxElxs(cm, t, request);
			int curelxm = cu.getElixir().intValue();
			if (value + curelxm > max) {
				cu.setElixir(Integer.valueOf(max));
				value = max + value - curelxm;
			} else {
				cu.setElixir(Integer.valueOf(curelxm + value));
				value = 0;
			}
			if (value > 0) {
				int lefttime = this.getLeftTime(request, t, type, tmp, value);
				tmp.setLefttime(t - lefttime * 1000L);
			} else {
				tmp.setLefttime(t);
			}
			tmp.setBoosttime(t);
			tmp.setBoosttime2(t + bu.getSpeedboos() * 1000L);
			tmp.setLeft(0);
			cm.getElxms().set(index, tmp);
		} else if (type.equals("DAKM")) {
			Dakm tmp = (Dakm) cm.getDakms().get(index);
			if (tmp.getUpgradeEnd() > t) {
				throw new SignException(
						"act_boost:no DAKM or DAKM can not work", 2);
			}
			Building bu = getBuildSettingXML(request).findBuByID(type);
			String[] strs = ((String) bu.getLv().get(tmp.getLv() - 1))
					.split(";");
			// String costtype = strs[7].substring(0, 1);
			int costneed = Integer.parseInt(strs[7].substring(1));

			if (cu.getGem().intValue() < costneed) {
				throw new SignException("act_boost:not enough gem", 2);
			}
			// 已经加速中不能重复加速
			if (tmp.getBoosttime2() >= t) {
				throw new SignException("act_boost:last boost is not end", 2);
			}
			cu.setGem(Integer.valueOf(cu.getGem().intValue() - costneed));
			// 加速时候先收取一次
			int value = getProductValue(request, t, type, tmp);
			int max = getMaxDaks(cm, t, request);
			int curdaks = cu.getDark().intValue();
			if (value + curdaks > max) {
				cu.setDark(Integer.valueOf(max));
				value = max + value - curdaks;
			} else {
				cu.setDark(Integer.valueOf(curdaks + value));
				value = 0;
			}
			if (value > 0) {
				int lefttime = this.getLeftTime(request, t, type, tmp, value);
				tmp.setLefttime(t - lefttime * 1000L);
			} else {
				tmp.setLefttime(t);
			}
			tmp.setBoosttime(t);
			tmp.setBoosttime2(t + bu.getSpeedboos() * 1000L);
			tmp.setLeft(0);
			cm.getDakms().set(index, tmp);
		} else if (type.equals("BARK")) {
			Tran tmp = (Tran) cm.getBarks().get(index);
			if (tmp.getUpgradeEnd() > t) {
				throw new SignException(
						"act_mineboost:no BARK or BARK can not work", 2);
			}
			Building bu = getBuildSettingXML(request).findBuByID(type);
			// 类型;需求等级(HT/User);花费;建造时间;矿脉容量/dect总数;生产速率;建造经验;加速费用;
			String[] strs = ((String) bu.getLv().get(tmp.getLv() - 1))
					.split(";");
			// String costtype = strs[7].substring(0, 1);
			int costneed = Integer.parseInt(strs[7].substring(1));
			if (cu.getGem().intValue() < costneed) {
				throw new SignException("act_boost:not enough gem", 2);
			}
			cu.setGem(Integer.valueOf(cu.getGem().intValue() - costneed));
			if (tmp.getBoosttime2() < t) {
				tmp.setBoosttime(t);
				tmp.setBoosttime2(t + bu.getSpeedboos() * 1000L);
			} else {
				tmp.setBoosttime2(tmp.getBoosttime2() + bu.getSpeedboos()
						* 1000L);
			}
			cm.getBarks().set(index, tmp);
		} else if (type.equals("BKDK")) {
			Trdk tmp = (Trdk) cm.getBkdks().get(index);
			if (tmp.getUpgradeEnd() > t) {
				throw new SignException(
						"act_boost:no BKDK or BKDK can not work", 2);
			}
			Building bu = getBuildSettingXML(request).findBuByID(type);

			String[] strs = ((String) bu.getLv().get(tmp.getLv() - 1))
					.split(";");
			// String costtype = strs[7].substring(0, 1);
			int costneed = Integer.parseInt(strs[7].substring(1));

			if (cu.getGem().intValue() < costneed) {
				throw new SignException("act_boost:not enough gem", 2);
			}
			cu.setGem(Integer.valueOf(cu.getGem().intValue() - costneed));

			if (tmp.getBoosttime2() < t) {
				tmp.setBoosttime(t);
				tmp.setBoosttime2(t + bu.getSpeedboos() * 1000L);
			} else {
				tmp.setBoosttime2(tmp.getBoosttime2() + bu.getSpeedboos()
						* 1000L);
			}
			cm.getBkdks().set(index, tmp);
		}
		cm.setCcuser(cu);
		MemCacheUtil.setObject("cm_" + cm.getUid().intValue(), cm);
	}

	public void getFriendsXML(HttpServletRequest request, StringBuffer sbf)
			throws Exception {
		sbf.append("{");

		int id = Integer.parseInt(request.getParameter("tk").substring(0,
				request.getParameter("tk").indexOf("_")));
		CcMap cm = (CcMap) MemCacheUtil.getObject("cm_" + id);
		Hashtable<String,String> ht = new Hashtable<String,String>();
		EloUserDAO sud = (EloUserDAO) getBean(request, "eloUserDAO");
		CocSetting ss = sud.findcs();
		CcEloUser sus = sud.findByID(id);
		String mySnsId = sus.getSnsid();
		String v3proxy = ss.getV3proxy();
		String v3ip = ss.getV3ip();
		if ((v3proxy != null) && (v3proxy.length() > 1)) {
			v3ip = com.coc.util.PubFun.getManagerHost(request, 1).split(":")[0]
					+ ":"
					+ com.coc.util.PubFun.getNginxHost(request, 1).split(":")[1]
					+ "/" + v3proxy;
		}
		String URL_REST_SERVER_v3 = "http://" + v3ip;

		if (ss.getSnstype().equals("qq")) {
			List<String> frili = new ArrayList<String>();
			CcEloUser su = sud.findByID(id);
			int lostcount = 0;
			String urlbase = "/v3/relation/get_app_friends";
			urlbase = URLEncoder.encode(urlbase, "utf-8");
			urlbase = "GET&" + urlbase;
			String postdata_v3 = "openid=" + su.getSnsid() + "&openkey="
					+ cm.getCcuser().getOpenkey() + "&appid=" + ss.getAppid()
					+ "&pf=qzone";

			String md5Str = sortPostData(postdata_v3);
			md5Str = URLEncoder.encode(md5Str, "utf-8");
			urlbase = urlbase + "&" + md5Str;
			String Algorithm = "HmacSHA1";
			SecretKey secretKey = new SecretKeySpec((ss.getAppkey() + "&")
					.getBytes(), Algorithm);
			Mac mac = Mac.getInstance(Algorithm);
			mac.init(secretKey);
			byte[] result = mac.doFinal(urlbase.getBytes());
			String sig = Base64.encodeToString(result);
			sig = URLEncoder.encode(sig, "utf-8");
			String _token_v3 = doHttpClientGet(URL_REST_SERVER_v3
					+ "/v3/relation/get_app_friends?" + postdata_v3 + "&sig="
					+ sig);
			System.out.println("qzone friend :" + _token_v3);
			JSONObject jsonobj = JSONObject.fromObject(_token_v3);
			String ret = jsonobj.getString("ret");

			if (ret.equals("0")) {
				String is_lost = jsonobj.getString("is_lost");
				while (is_lost.equals("1")) {
					System.out.println("qzone lost !!!!!!!!!!!!!");
					lostcount++;
					_token_v3 = doHttpClientGet(URL_REST_SERVER_v3
							+ "/v3/relation/get_app_friends?" + postdata_v3
							+ "&sig=" + sig);
					System.out.println("lost qzone friend :" + _token_v3);
					jsonobj = JSONObject.fromObject(_token_v3);
					ret = jsonobj.getString("ret");
					is_lost = jsonobj.getString("is_lost");
				}
				JSONArray ja = jsonobj.getJSONArray("items");
				for (int i = 0; i < ja.size(); i++) {
					JSONObject friidobj = (JSONObject) ja.get(i);
					String friopid = friidobj.getString("openid");
					if ((!ht.contains(friopid)) && (!friopid.equals(mySnsId))) {
						ht.put(friopid, friopid);
						frili.add(friopid);
					}
				}
			}

			urlbase = "/v3/relation/get_app_friends";
			urlbase = URLEncoder.encode(urlbase, "utf-8");
			urlbase = "GET&" + urlbase;
			postdata_v3 = "openid=" + su.getSnsid() + "&openkey="
					+ cm.getCcuser().getOpenkey() + "&appid=" + ss.getAppid()
					+ "&pf=pengyou";
			md5Str = sortPostData(postdata_v3);
			md5Str = URLEncoder.encode(md5Str, "utf-8");
			urlbase = urlbase + "&" + md5Str;
			Algorithm = "HmacSHA1";
			secretKey = new SecretKeySpec((ss.getAppkey() + "&").getBytes(),
					Algorithm);
			mac = Mac.getInstance(Algorithm);
			mac.init(secretKey);
			result = mac.doFinal(urlbase.getBytes());
			sig = Base64.encodeToString(result);
			sig = URLEncoder.encode(sig, "utf-8");
			_token_v3 = doHttpClientGet(URL_REST_SERVER_v3
					+ "/v3/relation/get_app_friends?" + postdata_v3 + "&sig="
					+ sig);
			System.out.println("pengyou friend :" + _token_v3);
			jsonobj = JSONObject.fromObject(_token_v3);
			ret = jsonobj.getString("ret");
			if (ret.equals("0")) {
				String is_lost = jsonobj.getString("is_lost");
				while (is_lost.equals("1")) {
					System.out.println("pengyou lost !!!!!!!!!!!!!");
					lostcount++;
					_token_v3 = doHttpClientGet(URL_REST_SERVER_v3
							+ "/v3/relation/get_app_friends?" + postdata_v3
							+ "&sig=" + sig);
					System.out.println("lost pengyou friend :" + _token_v3);
					jsonobj = JSONObject.fromObject(_token_v3);
					ret = jsonobj.getString("ret");
					is_lost = jsonobj.getString("is_lost");
				}
				JSONArray ja = jsonobj.getJSONArray("items");
				for (int i = 0; i < ja.size(); i++) {
					JSONObject friidobj = (JSONObject) ja.get(i);
					String friopid = friidobj.getString("openid");
					if ((!ht.contains(friopid)) && (!friopid.equals(mySnsId))) {
						ht.put(friopid, friopid);
						frili.add(friopid);
					}
				}

			}

			urlbase = "/v3/relation/get_app_friends";
			urlbase = URLEncoder.encode(urlbase, "utf-8");
			urlbase = "GET&" + urlbase;
			postdata_v3 = "openid=" + su.getSnsid() + "&openkey="
					+ cm.getCcuser().getOpenkey() + "&appid=" + ss.getAppid()
					+ "&pf=tapp";
			md5Str = sortPostData(postdata_v3);
			md5Str = URLEncoder.encode(md5Str, "utf-8");
			urlbase = urlbase + "&" + md5Str;

			result = mac.doFinal(urlbase.getBytes());
			sig = Base64.encodeToString(result);
			sig = URLEncoder.encode(sig, "utf-8");
			_token_v3 = doHttpClientGet(URL_REST_SERVER_v3
					+ "/v3/relation/get_app_friends?" + postdata_v3 + "&sig="
					+ sig);
			System.out.println("tapp friend :" + _token_v3);
			if (_token_v3.indexOf("null") == -1) {
				jsonobj = JSONObject.fromObject(_token_v3);
				ret = jsonobj.getString("ret");

				if (ret.equals("0")) {
					JSONArray ja = jsonobj.getJSONArray("items");
					for (int i = 0; i < ja.size(); i++) {
						JSONObject friidobj = (JSONObject) ja.get(i);
						String friopid = friidobj.getString("openid");
						if ((!ht.contains(friopid))
								&& (!friopid.equals(mySnsId))) {
							ht.put(friopid, friopid);
							frili.add(friopid);
						}
					}
				}
			}

			String uids = "";
			for (int i = 0; i < frili.size(); i++) {
				String friopenid = (String) frili.get(i);
				CcEloUser sufri = sud.findBySNSID(friopenid);
				if (sufri != null) {
					if (uids.equals(""))
						uids = sufri.getId() + "";
					else {
						uids = uids + "," + sufri.getId();
					}
				}
			}

			if (uids.equals("")) {
				uids = MemCacheUtil.getValue(id + "_friends");
				if ((uids == null) || (uids.equals("null")))
					uids = "";
			} else {
				MemCacheUtil.setValue(id + "_friends", uids);
			}

			sbf.append("\"friends\":[");
			String[] uid = uids.split(",");
			for (int i = 0; i < uid.length; i++) {
				CcEloUser cu = sud.findByID(Integer.parseInt(uid[i]));
				if (i != 0) {
					sbf.append(",");
				}
				sbf.append("{\"id\":\"" + uid[i] + "\",\"name\":\""
						+ cu.getName() + "\",\"portrait\":\""
						+ cu.getLastportrait() + "\"}");
			}
			sbf.append("]}");
		}

	}

	// 取金币上限
	private int getMaxGold(CcMap cm, long t, HttpServletRequest request) {
		// HT默认算1000
		int max = 1000;
		// 遍历金库
		for (int i = 0; i < cm.getGolss().size(); i++) {
			Gols gols = (Gols) cm.getGolss().get(i);
			int lv = gols.getLv();
			Building bu = getBuildSettingXML(request).findBuByID("GOLS");
			String[] strs = ((String) bu.getLv().get(lv - 1)).split(";");
			max += Integer.parseInt(strs[4]);
		}
		return max;
	}

	// 去紫水上限,计算同金币上限
	private int getMaxElxs(CcMap cm, long t, HttpServletRequest request) {
		int max = 1000;
		for (int i = 0; i < cm.getElxss().size(); i++) {
			Elxs gols = (Elxs) cm.getElxss().get(i);
			int lv = gols.getLv();
			Building bu = getBuildSettingXML(request).findBuByID("ELXS");
			String[] strs = ((String) bu.getLv().get(lv - 1)).split(";");
			max += Integer.parseInt(strs[4]);
		}
		return max;
	}

	private int getMaxDaks(CcMap cm, long t, HttpServletRequest request) {
		int max = 0;
		for (int i = 0; i < cm.getDakss().size(); i++) {
			Daks gols = (Daks) cm.getDakss().get(i);
			int lv = gols.getLv();
			Building bu = getBuildSettingXML(request).findBuByID("DAKS");
			String[] strs = ((String) bu.getLv().get(lv - 1)).split(";");
			max += Integer.parseInt(strs[4]);
		}
		return max;
	}

	// 取当前能造兵数量
	private int getCampEmpty(CcMap cm, long t, HttpServletRequest request) {
		int campspacecount = 0;
		// 当前队列空间
		int processspacecount = 0;
		int campspacemax = 0;
		for (int i = 0; i < cm.getBarks().size(); i++) {
			Tran tran = (Tran) cm.getBarks().get(i);
			String[] units = tran.getProcess().split(",");
			for (int j = 0; j < units.length; j++) {
				if (units[j].length() > 1) {
					Troops trs = getBuildSettingXML(request).findTrByID(
							units[j].substring(0, units[j].indexOf("|")));
					processspacecount = processspacecount
							+ trs.getSpace()
							* Integer.parseInt(units[j].substring(units[j]
									.indexOf("|") + 1));
				}
			}
		}
		for (int i = 0; i < cm.getBkdks().size(); i++) {
			Trdk tran = (Trdk) cm.getBkdks().get(i);
			String[] units = tran.getProcess().split(",");
			for (int j = 0; j < units.length; j++) {
				if (units[j].length() > 1) {
					Troops trs = getBuildSettingXML(request).findTrByID(
							units[j].substring(0, units[j].indexOf("|")));
					processspacecount = processspacecount
							+ trs.getSpace()
							* Integer.parseInt(units[j].substring(units[j]
									.indexOf("|") + 1));
				}
			}
		}
		String[] camps = cm.getCamplist().split(",");
		for (int i = 0; i < camps.length; i++) {
			if (camps[i].length() > 1) {
				Troops trs = getBuildSettingXML(request).findTrByID(
						camps[i].substring(0, camps[i].indexOf("|")));
				campspacecount = campspacecount
						+ trs.getSpace()
						* Integer.parseInt(camps[i].substring(camps[i]
								.indexOf("|") + 1));
			}
		}
		for (int i = 0; i < cm.getCamps().size(); i++) {
			Camp camp = (Camp) cm.getCamps().get(i);
			Building bu = getBuildSettingXML(request).findBuByID("CAMP");
			int lv = camp.getLv();

			String[] strs = ((String) bu.getLv().get(lv - 1)).split(";");
			campspacemax += Integer.parseInt(strs[4]);
		}
		return campspacemax - campspacecount - processspacecount;
	}
}
